package com.zs.mybatis.sqlSession;

import com.zs.mybatis.config.Configuration;
import com.zs.mybatis.config.MappedStatement;
import com.zs.mybatis.excutor.SimpleSqlExecutor;
import com.zs.mybatis.excutor.SqlExecutor;

import java.beans.IntrospectionException;
import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.List;

public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;
    //sql执行器
    private SqlExecutor simpleSqlExecutor = new SimpleSqlExecutor();

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    public <E> List<E> selectList(String statementId, Object...param) throws IllegalAccessException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
        MappedStatement mappedStatement = configuration.getMap().get(statementId);
        List<E> list = simpleSqlExecutor.query(configuration, mappedStatement, param);
        return list;
    }

    public <E> E selectone(String statementId, Object...param) throws IllegalAccessException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
        MappedStatement mappedStatement = configuration.getMap().get(statementId);
        List<E> list = selectList(statementId, param);
        if (list != null && list.size() == 1) {
            return list.get(0);
        } else {
            throw new RuntimeException("返回结果过多");
        }
    }

    public void close () throws SQLException {
        simpleSqlExecutor.close();
    }

    public <T> T getMapper(Class<?> mapperClass) {
        //创建代理对象
        T o = (T) Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //获取mapper全限定mind，与xml命名空间隐射
                String className = method.getDeclaringClass().getName();
                //方法名
                String name = method.getName();
                //返回类型
                Type genericReturnType = method.getGenericReturnType();
                String key = className + "." + name;
                //判定返回值是否含有泛型，没有则为搜索一个
                if (genericReturnType instanceof ParameterizedType) {
                    return selectList(key, args);
                } else {
                    return selectone(key, args);
                }
            }
        });
        return o;
    }

}
